#include "TestClient.h"

#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include "../unity.h"

using std::string;

TestClient::TestClient():m_fd(-1), m_usedSize(0), m_size(0)
{

}

TestClient::~TestClient()
{
	if (m_fd != -1)
	{
		::close(m_fd);
		//shutdown(m_fd, SHUT_RDWR);
		m_fd = -1;
	}
}

int TestClient::connect(const std::string& ip, int port)
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		return -1;

	if (setNoBlocking(sockfd) < 0)
		return -1;

	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	if (inet_pton(AF_INET, ip.c_str(), &addr.sin_addr) <= 0)
		return -1;

	if (::connect(sockfd, (sockaddr*) &addr, sizeof(addr)) < 0)
	{
		if (errno != EINPROGRESS) // 异步返回
			return -1;
	}

	if (setTcpNoDelay(sockfd) < 0)
		return -1;

	return (m_fd = sockfd);
}
	
int TestClient::close()
{
	if (m_fd == -1)
		return 0;
	::close(m_fd);
	m_fd = -1;
	return 1;
}

int TestClient::writeProcess(void*)
{
	if (this->m_usedSize >= this->m_size)
	{
		this->m_size = generateMsg(this->m_buffer, LOGIN);
		this->m_usedSize = 0;
	}

	int readSize = 0;
	do 
	{
		readSize = write(this->m_fd, this->m_buffer + this->m_usedSize,
				this->m_size - this->m_usedSize);
		this->m_usedSize += readSize;
		if (readSize < 0)
		{
			// 错误处理可能还需更严谨
			if (errno == EINTR)
				continue;
			else if (errno = EAGAIN)
				break;
			else
			{
				errorLog("client write error!");
				return -1;
			}
		}
		else if (readSize == 0)
		{
			this->close();
			break;
		}
	}
	while (this->m_usedSize < this->m_size);

	return this->m_usedSize;
}

int TestClient::readProcess(void*)
{
	unsigned char result = 0;

	ssize_t readSize = 0;

	do
		readSize = read(this->m_fd, &result,1);
	while (readSize < 0 && errno == EINTR);

	if (readSize < 0 && errno != EAGAIN)
	{
		errorLog("read error");
		return -1;
	}
	else if (readSize == 0)
	{
		this->close();
		return 0;
	}
	return result;
}

// 生成测试用户名
string TestClient::generateUsername()
{
	string str = "test";
	char buffer[10];
	sprintf(buffer,"%d",rand()%100000);
	str += (buffer);
	return str;
}

// 生成协议字符串
int TestClient::generateMsg(unsigned char* buffer, ClientMsg msg)
{
	buffer[0] = msg;
	string usr = generateUsername();
	buffer[1] = usr.size();
	memcpy(buffer+2,usr.c_str(),usr.size());
	buffer[2+usr.size()] = 3;
	buffer[3+usr.size()] = 'a';
	buffer[4+usr.size()] = 'y';
	buffer[5+usr.size()] = 'z';

	return 6+usr.size();
}
